Add preamble section and preserve action to SDKs#1713
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the SDK surface area for system-prompt customization to match the runtime’s newer model by adding a dedicated preamble section ID and a preserve section override action, then validating the new section via cross-SDK E2E coverage and documentation updates.
Changes:
- Added
preambleas a first-class system message section identifier, and clarifiedidentity/tool_instructionsas section groups in constants/docs across SDKs. - Added the
preserveoverride action (no-op marker used to protect a leaf section from a group-levelremove) in language SDK types/enums/docs (Rust docs only, since Rust uses free-form strings). - Added a new E2E scenario (
should_use_replaced_preamble_section_in_response) and shared replay snapshot to verifypreamblereplacement flows through SDK → RPC → CLI.
Show a summary per file
| File | Description |
|---|---|
| test/snapshots/system_message_sections/should_use_replaced_preamble_section_in_response.yaml | New shared replay snapshot for the preamble-replacement persona test. |
| rust/tests/e2e/system_message_sections.rs | Adds Rust E2E test covering preamble replacement behavior. |
| rust/src/types.rs | Updates SectionOverride doc comments to include the new preserve action. |
| python/e2e/test_system_message_sections_e2e.py | Adds Python E2E test covering preamble replacement behavior. |
| python/copilot/session.py | Extends Python system-message section/action types and metadata (preamble, preserve), updates section descriptions. |
| nodejs/test/e2e/system_message_sections.e2e.test.ts | Adds Node E2E test covering preamble replacement behavior. |
| nodejs/src/types.ts | Extends Node system-message section/action types and metadata (preamble, preserve), updates section descriptions. |
| nodejs/README.md | Documents preamble, section groups, and the 5th action (preserve). |
| java/src/test/java/com/github/copilot/SystemMessageSectionsIT.java | Adds Java E2E/integration test for preamble; updates constant-count assertions. |
| java/src/main/java/com/github/copilot/rpc/SystemMessageSections.java | Adds PREAMBLE constant and clarifies IDENTITY as a group. |
| java/src/main/java/com/github/copilot/rpc/SectionOverrideAction.java | Adds PRESERVE enum value with Javadoc describing semantics. |
| go/types.go | Adds SectionPreamble and SectionActionPreserve, updates SectionIdentity docs to describe group semantics. |
| go/README.md | Documents SectionPreamble, section groups, and the 5th action (preserve). |
| go/internal/e2e/system_message_sections_e2e_test.go | Adds Go E2E test covering preamble replacement behavior. |
| dotnet/test/E2E/SystemMessageSectionsE2ETests.cs | Adds .NET E2E test covering preamble replacement behavior. |
| dotnet/src/Types.cs | Adds Preamble section identifier and Preserve override action. |
| dotnet/README.md | Documents Preamble, section groups, and the 5th action (Preserve). |
| docs/getting-started.md | Documents preamble, section groups, and the 5th action (preserve). |
Copilot's findings
- Files reviewed: 18/18 changed files
- Comments generated: 1
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by SDK Consistency Review Agent for issue #1713 · sonnet46 1.4M
Comments that could not be inline-anchored
go/README.md:168
This inline parameter-description list was not updated alongside the "Available section constants" paragraph below. SectionPreamble is missing from the keys: list, and the description of SectionIdentity should note it is a section group.
Suggested update:
- **customize**: Selectively override individual sections via `Sections` map (keys: `SectionPreamble`, `SectionIdentity` (group), `SectionTone`, `SectionToolEfficiency`, `SectionEnvironmentContext`, `SectionCodeChangeRules`, `Sec…
</details>
|
Thanks, good catch. Fixed in 077a390: added I left the group annotation out of that terse one-liner intentionally; the group semantics for |
This comment has been minimized.
This comment has been minimized.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a 'should_use_replaced_preamble_section_in_response' E2E test to all six SDKs (Node, Go, Python, .NET, Java, Rust) exercising the new 'preamble' section ID end-to-end, with a shared replay snapshot. Updates the Java SystemMessageSections constant-count assertion from 11 to 12. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the unsupported 'a warning is emitted' claim from the system message customization section so it matches the silent-fallback behavior documented in the language READMEs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The new preamble test docstring exceeded the 100-char limit, failing 'ruff check' in the Python SDK Tests CI job across all platforms. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The SystemMessage parameter-reference table's inline section-constant list still started at SectionIdentity. Add SectionPreamble so it matches the dedicated 'Available section constants' list and the other SDKs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
077a390 to
11ad399
Compare
Cross-SDK Consistency Review ✅This PR maintains excellent consistency across all six SDK implementations. Here's what I verified: New
|
| SDK | Addition |
|---|---|
| Node.js | "preamble" added to SystemMessageSection union type + SYSTEM_MESSAGE_SECTIONS record |
| Python | "preamble" added to SystemMessageSection Literal type + SYSTEM_MESSAGE_SECTIONS dict |
| Go | SectionPreamble = "preamble" constant added |
| .NET | SystemMessageSection.Preamble static property added |
| Java | SystemMessageSections.PREAMBLE = "preamble" constant added (inherited by SystemPromptSections) |
| Rust | Doc comments updated (by design — Rust uses free-form strings) |
New preserve action — all 6 SDKs ✅
| SDK | Addition |
|---|---|
| Node.js | "preserve" added to SectionOverrideAction union type |
| Python | "preserve" added to SectionOverrideAction Literal union |
| Go | SectionActionPreserve = "preserve" constant added |
| .NET | SectionOverrideAction.Preserve enum member added |
| Java | SectionOverrideAction.PRESERVE("preserve") enum member added |
| Rust | Doc comments updated (free-form string; consistent with Rust's existing approach) |
Ordering consistency ✅
The preserve action is inserted after prepend and before transform/callback in every SDK — consistent placement across all typed definitions.
The preamble section is placed before identity in every SDK — consistent placement.
E2E tests — all 6 SDKs ✅
Each SDK adds a should_use_replaced_preamble_section_in_response test exercising the same scenario (replacing preamble with a gardening persona, asserting the persona surfaces in the response), all backed by the shared snapshot at test/snapshots/system_message_sections/should_use_replaced_preamble_section_in_response.yaml.
Documentation ✅
docs/getting-started.md,nodejs/README.md,go/README.md, anddotnet/README.mdall updated withpreamblesection, group concept, andpreserveaction.- Python, Java, and Rust READMEs don't contain the detailed section listing, so they correctly don't require updates.
No inconsistencies found
This PR is a well-executed cross-SDK change with high parity. No gaps identified.
Generated by SDK Consistency Review Agent for issue #1713 · sonnet46 1.5M · ◷
Why
The runtime recently reworked system prompt customization (copilot-agent-runtime#10025) to fix a bug where
identity: { action: "replace" }silently deleted sibling sections (tone, tool efficiency, etc.). That fix introduced a newpreamblesection ID and a newpreserveaction, but the SDKs didn't expose either, so clients couldn't target just the identity preamble or opt a section out of a group-level remove.What
This brings all six SDKs in line with the new runtime model:
preamblesection — targets just the identity preamble without touching its sibling sub-sections. Theidentityandtool_instructionsIDs are now documented as section groups.preserveaction — a no-op that protects an individually-addressable section (e.g.tone) from a group-levelremoveon its parent group.Changes are applied consistently across the type/constant definitions for Node, Go, Python, .NET, and Java. Rust uses free-form section/action strings, so only its doc comments needed updating. Docs in
getting-started.mdand the Node/Go/.NET READMEs are updated to describe the groups and the fifth action.Tests
Added an end-to-end
should_use_replaced_preamble_section_in_responsetest to all six SDKs, backed by a shared replay snapshot undertest/snapshots/. The test replaces thepreamblesection with a custom persona and asserts the persona surfaces in the assistant's reply, validating the customization flows through the full SDK -> RPC -> CLI stack.A couple of notes for reviewers:
${system}placeholder, so the test asserts on observable assistant output rather than raw prompt bytes.PREAMBLE.preserve-specific E2E test was intentionally omitted: its effect lives entirely in the system-prompt bytes that the harness normalizes away, so it would carry no real signal. The constant additions are the meaningful SDK surface here.Verified: Node/Go/Python E2E pass on replay; .NET/Java/Rust compile and format clean.